using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using LastFmLib.API20.Album;
using LastFmLib.API20.Artist;
using LastFmLib.API20.Types;
using LastFmLib.API20.User;
using StaffWarsFm.Lib.Data;

namespace StaffWarsFm.Questions
{
    public static class CacheStatus
    {
        public static bool AlbumCachePopulated, ArtistCachePopulated;
        public static User[] CurrentUsers;
    }

    public static class Cache<T>
        where T : class 
    {
        private static AlbumQuestionService _albumService = new AlbumQuestionService();
        private static ArtistQuestionService _artistService = new ArtistQuestionService();
        private static List<char> _artistSearchedQuerys = new List<char>(), _albumSearchedQuerys = new List<char>(); 

        public static List<T> Items
        {
            get; private set;
        }

        private static string _path = Environment.CurrentDirectory + "\\" + typeof (T).Name + ".xml";

        static Cache()
        {
            Items = new List<T>();
        }

        public static bool Contains(T item)
        {
            return Items.Contains(item);
        }

        public static bool Contains(Func<T, bool> test)
        {
            return Items.Count(test) != 0;
        }

        public static void Add(T item)
        {
            Add(new [] { item });
        }

        public static void Add(IEnumerable<T> items)
        {
            Items.AddRange(items.Where(i => false == Contains(i)));
        }

        public static IEnumerable<T> Get(Func<T, bool> where)
        {
            return Items.Where(where);
        }

        public static IEnumerable<T> Get(int numItems, T exclude)
        {
            var items = Items.Where(i => exclude != i).Take(numItems);

            if(items.Count() < numItems)
            {
                WaitForItems();

                items.Union(Items.Where(i => exclude != i).Take(numItems - items.Count()));
            }

            return items;
        }
        
        private static void WaitForItems()
        {
            int wait = 0;
            if (typeof(T) == typeof(ArtistInfo) && false == CacheStatus.ArtistCachePopulated)
            {
                PopulateArtistCache(CacheStatus.CurrentUsers);
            }
            else if (typeof(T) == typeof(AlbumInfo) && false == CacheStatus.AlbumCachePopulated)
            {
                PopulateAlbumCache(CacheStatus.CurrentUsers);
            }
            else
            {
                throw new Exception(
                    string.Format("Cant get any more of {0}...", typeof(T).Name)
                );
            }
        }



        private static void PopulateArtistCache(IEnumerable<User> users)
        {
            if(CacheStatus.ArtistCachePopulated)
            {
                return;
            }

            foreach (var user in users)
            {
                var getArtists = new UserGetTopArtists(user.UserName, LastFmLib.API20.modEnums.ChartPeriod.TwelveMonths);

                getArtists.AuthData = Util.GetAuthData();
                getArtists.Start();

                if (getArtists.Succeeded)
                {
                    foreach (var artist in getArtists.Result)
                    {
                        if (false == Cache<ArtistInfo>.Contains(a => a.MbId.ToString() == artist.MbId.ToString()))
                        {
                            try
                            {
                                Cache<ArtistInfo>.Add(_artistService.GetArtistInfo(artist.MbId));
                            }
                            catch (Exception)
                            {
                                //bleep
                            }
                        }
                    }
                }
            }
            CacheStatus.ArtistCachePopulated = true;
        }

        private static void PopulateAlbumCache(IEnumerable<User> users)
        {
            if(CacheStatus.AlbumCachePopulated)
            {
                return;
            }

            foreach (var user in users)
            {
                var getAlbums = new UserGetTopAlbums(user.UserName, LastFmLib.API20.modEnums.ChartPeriod.TwelveMonths);

                getAlbums.AuthData = Util.GetAuthData();
                getAlbums.Start();

                if (getAlbums.Succeeded)
                {
                    foreach (var album in getAlbums.Result.Where(t => false == Cache<AlbumInfo>.Contains(a => a.MbId == t.MbId)).Take(10))
                    {    
                        try
                        {
                            Cache<AlbumInfo>.Add(_albumService.GetAlbumInfo(album.MbId));
                        }
                        catch (Exception)
                        {
                            //moo
                        }
                    }
                }
            }
            CacheStatus.AlbumCachePopulated = true;
        }
    }
}
